import _ from "lodash";
import { app, ipcRenderer } from "electron";
import BaseController from "../base/BaseController";
import { controllers } from "./mapping";
import { EventEmitter } from "events";
import DataStore from "../store/index";
import { routeJoin, JsonResultUtil } from "../tools/index";
import { Code } from "../tools/code";

export default async (context: { handle: Function; send: Function }) => {
  const eventMapping = new EventEmitter();
  const scope = new DataStore();
  const socketMapping = new Map();

  const emit = (key: string, ...args: Array<any>) => {
    const eventName = "$event-" + key;
    if (
      eventMapping.eventNames().findIndex((name) => name === eventName) >= 0
    ) {
      console.log("emit", eventName, ...args);
      eventMapping.emit(eventName, ...args);
      return true;
    }
    return false;
  };

  const addListener = (key: string, value: Array<any>) => {
    try {
      const eventName = "$event-" + key;
      const callback = (...args: Array<any>) =>
        context.send(eventName, ...args);
      eventMapping.addListener(eventName, callback);
      scope.set(eventName, { value, callback });
    } catch (error) {
      console.log(error);
    }
  };

  const removeListener = (key: string) => {
    try {
      const eventName = "$event-" + key;
      let { callback } = scope.get(eventName);
      eventMapping.removeListener(eventName, callback);
      scope.remove(eventName);
    } catch (error) {}
  };

  let store = {
    ipcRenderer,
    scope,
    emit,
    addListener,
    removeListener,
  };

  const socket = (event: Event, key: string, args: Array<any>) => {
    console.log(key, args);
    const callback = socketMapping.get(key);
    try {
      if (typeof callback === "function") {
        return callback(Object.assign({ event }, store), ...args);
      }
    } catch (error) {
      console.log(error);
    }
    return JsonResultUtil(Code.not_found, "不存在该接口");
  };

  controllers.forEach((controller: typeof BaseController) => {
    let con = new controller(store);
    let $api = _.get(con, "$api");
    let $property: any = _.get(con, "$property");

    let interfaces = _.get(con, "$interfaces") as Array<{
      eventName: string;
      callback: Function;
      typeKey: string;
    }>;
    interfaces.forEach((item) => {
      let { eventName } = item;
      if ($api) {
        eventName = routeJoin($api, eventName);
      }
      console.log("socketMapping", eventName);
      socketMapping.set(eventName, (tools: any, ...args: Array<any>) => {
        let data: Array<any> = [];
        let propertys = _.get($property, item.typeKey);
        if (_.isArray(propertys)) {
          propertys.forEach((key: string) =>
            data.push(_.get(tools, key.match(/(?<=\$)[a-zA-Z]+/gi)))
          );
        }
        data = data.concat(args);
        return item.callback.call(con, ...data);
      });
    });
  });

  context.handle("send", (event: Event, ...args: Array<any>) => {
    try {
      let key = args[0];
      let argsValue = args.slice(1);
      console.log("send", key, argsValue);
      return socket(event, key, argsValue);
    } catch (error) {}
  });

  context.handle("listen", (event: Event, key: string, value: any) =>
    addListener(key, value)
  );

  context.handle("close-listen", (event: Event, key: string) =>
    removeListener(key)
  );
};
